#pragma once
#include "rpcrouter.hpp"
#include "rpc_registry.hpp"
#include "../common/dipatcher.hpp"
#include "../client/rpc_client.hpp"
#include"rpc_topic.hpp"

namespace rpc
{
    namespace server
    {
        class RegistryServer
        {
        public:
            using ptr = std::shared_ptr<RegistryServer>;
            RegistryServer(int port)
                : _pd_manager(std::make_shared<PDManager>()), _dispacher(std::make_shared<dipatcher>())
            {
                // dispacher设置
                auto cb = std::bind(&PDManager::onRequestServer, _pd_manager.get(), std::placeholders::_1, std::placeholders::_2);
                _dispacher->rigisteHandler<ServerRequest>(rpc::MY_TYPE::REQ_SERVICE, cb);
                // 服务端
                _server = rpc::ServerFactory::create(port);
                auto ms_cb = std::bind(&rpc::dipatcher::onMessage, _dispacher.get(), std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(ms_cb);
                auto CloseCallback = std::bind(&RegistryServer::close, this, std::placeholders::_1);
                _server->setCloseCallback(CloseCallback);
            }

            void start()
            {
                _server->start();
            }

            void close(const BaseConnection::ptr &conn)
            {
                _pd_manager->connectionShutDown(conn);
            }

        private:
            PDManager::ptr _pd_manager;
            dipatcher::ptr _dispacher;
            rpc::BaseServer::ptr _server;
        };

        class RpcServer
        {
        public:
            using ptr = std::shared_ptr<RpcServer>;
            RpcServer(const Address &access_addr, bool enableRegistry = false, const Address &registr_addr = Address())
                : _router(std::make_shared<rpc::server::rpcRouter>()),
                  _dispacher(std::make_shared<rpc::dipatcher>()),
                  _enableRegistry(enableRegistry),
                  _access_server_addr(access_addr)
            {
                if (_enableRegistry)
                {
                    _client_registry = std::make_shared<client::RegistryClient>(registr_addr.first, registr_addr.second);
                }
                auto cb = std::bind(&rpc::server::rpcRouter::onRpcRequest, _router.get(), std::placeholders::_1, std::placeholders::_2);
                _dispacher->rigisteHandler<rpc::RpcRequest>(rpc::MY_TYPE::REQ_RPC, cb);
                _server = rpc::ServerFactory::create(access_addr.second);
                auto ms_cb = std::bind(&rpc::dipatcher::onMessage, _dispacher.get(), std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(ms_cb);
            }
            void RegistryMethod(const ServiceDescribe::ptr &server)
            {
                if (_enableRegistry)
                {
                    delog("RegistryMethod开始组册方法");
                    _client_registry->registryMethod(server->getMethodName(), _access_server_addr);
                    delog("RegistryMethod注册方法结束");
                }
                _router->RegisterMethod(server);
            }
            void start()
            {
                _server->start();
            }

        private:
            Address _access_server_addr;
            bool _enableRegistry;
            rpcRouter::ptr _router;
            dipatcher::ptr _dispacher;
            client::RegistryClient::ptr _client_registry;
            rpc::BaseServer::ptr _server;
        };

        class TopicServer
        {
        public:
            using ptr = std::shared_ptr<TopicServer>;
            TopicServer(int port)
                : _topic_manager(std::make_shared<TopicManager>()), _dispacher(std::make_shared<dipatcher>())
            {
                // dispacher设置
                auto cb = std::bind(&TopicManager::onTopicRequestor, _topic_manager.get(), std::placeholders::_1, std::placeholders::_2);
                _dispacher->rigisteHandler<TopicRequest>(rpc::MY_TYPE::REQ_TOPIC, cb);
                // 服务端
                _server = rpc::ServerFactory::create(port);
                auto ms_cb = std::bind(&rpc::dipatcher::onMessage, _dispacher.get(), std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(ms_cb);
                auto CloseCallback = std::bind(&TopicServer::close, this, std::placeholders::_1);
                _server->setCloseCallback(CloseCallback);
            }

            void start()
            {
                _server->start();
            }

            void close(const BaseConnection::ptr &conn)
            {
                _topic_manager->onShutDown(conn);
            }

        private:
            TopicManager::ptr _topic_manager;
            dipatcher::ptr _dispacher;
            rpc::BaseServer::ptr _server;
        };
    }
}